#if defined(_WIN32) || defined(_WIN64)
#include <winsock2.h>
#elif defined(__linux__)
#include <sys/socket.h>
#include <poll.h>
#else
#error "not support platform"
#endif


#include <errno.h>
#include <unistd.h>

#include "YXIO.h"
#include "YXLog.h"


/**
 * 读取一行数据（会修改sds的长度, 以便继续读取满足一行）
 * 若出现了连接关闭, 则返回 READ_EXIT
 * 若暂时没有数据可读或者异常, 则返回 READ_FAILED
 * 若一行数据过于长, 则返回 READ_UNABLE
 */
int read_line(int fd, sds buf) {
    sds p = buf + sds_len(buf);
    int  i    = 0;
    int  size = sds_free_len(buf);
    char c    = '\0';
    int  n;

    // 改成直接读取到buf, 而不是先读取到c, 再写入到buf？
    while ((i < size - 1) && (c != '\n')) {
        n = recv(fd, &c, 1, 0);
        if (n > 0) {
            if (c == '\r') {
                n = recv(fd, &c, 1, MSG_PEEK);
                if ((n > 0) && (c == '\n')) {
                    recv(fd, &c, 1, 0);
                } else {
                    c = '\n';
                }
            }
            p[i] = c;
            i++;
        } else {
            if (errno == EAGAIN) {
                sds_incr_len(buf, i);
                return READ_AGAIN;
            }
            return READ_FAILED;
        }
    }
    if (i == size - 1) {
        return READ_UNABLE;
    }
    sds_incr_len(buf, i);
    return READ_SUCCESS;
}

/**
 * 尽可能读取一次数据
 */
int read_once(int fd, sds buf) {
    int n = recv(fd, buf + sds_len(buf), sds_free_len(buf), 0);
    if (n > 0) {
        sds_incr_len(buf, n);
        return READ_SUCCESS;
    }
    if (n == -1 && errno == EAGAIN)
        return READ_AGAIN;
    return n;
}

/**
 * 读取 size 个字节的数据（会进行扩容）
 */
int read_all(int fd, sds *buf_ptr, int size) {
    sds buf = *buf_ptr;
    while (size) {
        int n = read_once(fd, buf);
        if (n == READ_SUCCESS) {
            if (sds_len(buf) == size) {
                break;
            }
            if (sds_free_len(buf) == 0) {
                buf      = sds_make_room(buf, sds_len(buf) * 0.5);
                *buf_ptr = buf;
            }
        } else if (n == READ_FAILED || n == READ_EXIT) {
            return n;
        }
    }
    return READ_SUCCESS;
}

int file_read_once(FILE *fp, sds buf) {
    int n = fread(buf + sds_len(buf), 1, sds_free_len(buf), fp);
    if (n > 0) {
        sds_incr_len(buf, n);
        return READ_SUCCESS;
    }
    return READ_FAILED;
}

/**
 * 读取完整个文件（会进行扩容）
 */
int file_read_all(char *path, sds *buf_ptr) {
    FILE *fp = fopen(path, "rb");

    if (fp == NULL) {
        return READ_FAILED;
    }

    sds buf = *buf_ptr;
    while (file_read_once(fp, buf) == READ_SUCCESS) {
        if (sds_free_len(buf) == 0) {
            buf      = sds_make_room(buf, sds_len(buf) * 0.5);
            *buf_ptr = buf;
        }
    }
    if (feof(fp)) {
        fclose(fp);
        return READ_SUCCESS;
    }
    fclose(fp);
    logErrno();
    return READ_FAILED;
}